package org.zsk.cs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zsk.cs.common.AppUtils;
import org.zsk.cs.dao.RoleDao;
import org.zsk.cs.dao.UserDao;
import org.zsk.cs.domain.po.IdentityAuth;
import org.zsk.cs.dao.IdentityAuthDao;
import org.zsk.cs.domain.po.Role;
import org.zsk.cs.domain.po.User;
import org.zsk.cs.domain.vo.IdentityAuthVo;
import org.zsk.cs.domain.vo.RoleVo;
import org.zsk.cs.exception.BizException;
import org.zsk.cs.service.IdentityAuthService;
import org.zsk.cs.service.RoleService;
import org.zsk.cs.service.UserService;
import org.zsk.cs.util.UserUtils;
import org.zsk.fastdev.assign.Assign;
import org.zsk.fastdev.bean.BeanUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 社区身份认证 serviceImpl
 * </p>
 *
 * @author zsk
 * @version 1.0
 * Created on 2020/03/26
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class IdentityAuthServiceImpl extends ServiceImpl<IdentityAuthDao,IdentityAuth> implements IdentityAuthService {

    private final UserService userService;
    private final RoleService roleService;
    private final UserDao userDao;
    private final RoleDao roleDao;
    private final IdentityAuthDao identityAuthDao;
    private final Assign assign;
    private final AppUtils appUtils;

    @Autowired
    public IdentityAuthServiceImpl(UserService userService, RoleService roleService, UserDao userDao, RoleDao roleDao, IdentityAuthDao identityAuthDao, Assign assign, AppUtils appUtils) {
        this.userService = userService;
        this.roleService = roleService;
        this.userDao = userDao;
        this.roleDao = roleDao;
        this.identityAuthDao = identityAuthDao;
        this.assign = assign;
        this.appUtils = appUtils;
    }

    @Override
    public boolean registerResidentBatch(IdentityAuthVo identityAuthVo) {
        if (identityAuthVo.getUserVoList().size()<=0){
            throw new IllegalArgumentException("批量注册居民非法集合大小");
        }
        List<User> userList=identityAuthVo.getUserVoList().stream().collect(ArrayList::new,(users, userVo) -> {
            User user=new User();
            try {
                assign.assign(userVo,user,"$username,$password");
            } catch (Exception e) {
                e.printStackTrace();
            }
            users.add(user);
        },ArrayList::addAll);
        IdentityAuth districtHead=appUtils.getDistrictHead();
        log.debug("社区长查询成功");
        try{
            userService.saveBatch(userList);
        }catch (Exception e){
            throw new BizException("用户名已存在:"+e.getMessage());
        }
        log.debug("批量添加用户成功");
        List<IdentityAuth> identityAuthList=userList.stream().collect(ArrayList::new,(identityAuths, user) -> {
            IdentityAuth identityAuth = new IdentityAuth();
            identityAuth.setUid(user.getId());
            identityAuth.setCommunity(districtHead.getCommunity());
            identityAuths.add(identityAuth);
        },ArrayList::addAll);
        saveBatch(identityAuthList);
        List<Long> userIds= userList.stream().map(User::getId).collect(Collectors.toList());
        roleService.addUserForRoleBatch(userIds, Collections.singletonList(4));
        log.debug("批量注册居民成功");
        return true;
    }

    @Override
    public boolean auditResidentIdentityAuth(IdentityAuthVo identityAuthVo) throws Exception {
        IdentityAuth identityAuth=new IdentityAuth();
        if (identityAuthVo.getStatus()==2){
            identityAuth.setAtime(new Date());
        }
        assign.assign(identityAuthVo,identityAuth,"$status,$id");
        boolean result=identityAuthDao.update(identityAuth,new LambdaUpdateWrapper<IdentityAuth>()
                .eq(IdentityAuth::getId,identityAuth.getId())
                .eq(IdentityAuth::getType,0))==1;
        if(result){
            IdentityAuth curIdentityAuth=identityAuthDao.selectById(identityAuth.getId());
            User user=userDao.selectById(curIdentityAuth.getUid());
            if (identityAuth.getStatus()==2){
                roleDao.addUserForRole(user.getId(),3);
            }else {
                roleDao.deleteUserForRole(user.getId(),3);
            }
        }
        return result;
    }

    @Override
    public boolean auditDistrictHeadIdentityAuth(IdentityAuthVo identityAuthVo) throws Exception {
        IdentityAuth identityAuth=new IdentityAuth();
        //审核通过添加审核时间
        if (identityAuthVo.getStatus()==2){
            identityAuth.setAtime(new Date());
        }
        assign.assign(identityAuthVo,identityAuth,"$status,$id");
        boolean result=identityAuthDao.update(identityAuth,new LambdaUpdateWrapper<IdentityAuth>()
                .eq(IdentityAuth::getId,identityAuth.getId())
                .eq(IdentityAuth::getType,1))==1;
        if (result){
            IdentityAuth curIdentityAuth=identityAuthDao.selectById(identityAuth.getId());
            User user=userDao.selectById(curIdentityAuth.getUid());
            if (identityAuth.getStatus()==2){
                roleDao.addUserForRole(user.getId(),2);
            }else {
                roleDao.deleteUserForRole(user.getId(),2);
            }
        }
        return result;
    }

    @Override
    public IdentityAuth getPersonalIdentityAuth() {
        return identityAuthDao.selectOne(new LambdaQueryWrapper<IdentityAuth>().eq(IdentityAuth::getUid, UserUtils.getCurrentUser().getId()));
    }

    @Override
    public Page<IdentityAuthVo> getWithUserNameByPage(IdentityAuthVo identityAuthVo) throws Exception {
        Page<IdentityAuth> page=new Page<>();
        assign.assign(identityAuthVo,page,"$current,$size");
        Page<IdentityAuth> identityAuthPage=page(page);
        return getIdentityAuthVoPage(identityAuthPage);
    }

    @Override
    public Page<IdentityAuthVo> districtHeadGetWithUserNameByPage(IdentityAuthVo identityAuthVo) throws Exception {
        //获取当前用户的社区长身份
        IdentityAuth districtHead=appUtils.getDistrictHead();
        Page<IdentityAuth> page=new Page<>();
        assign.assign(identityAuthVo,page,"$current,$size");
        //获取社区居民身份
        Page<IdentityAuth> identityAuthPage=page(page,new LambdaQueryWrapper<IdentityAuth>()
                .eq(IdentityAuth::getCommunity,districtHead.getCommunity().toString())
                .eq(IdentityAuth::getType,0));
        return getIdentityAuthVoPage(identityAuthPage);
    }

    /**
     * @param identityAuthPage 身份认证page
     * @return 转换后的page
     * @throws Exception
     */
    private Page<IdentityAuthVo> getIdentityAuthVoPage(Page<IdentityAuth> identityAuthPage) throws Exception {
        Page<IdentityAuthVo> identityAuthVoPage = new Page<>();
        //合并搜索结果
        List<IdentityAuthVo> identityAuthVoList = identityAuthPage.getRecords().stream().collect(LinkedList::new,(identityAuthVos, identityAuth) -> {
            User user = userDao.selectById(identityAuth.getUid());
            IdentityAuthVo curIdentityAuthVo = new IdentityAuthVo();
            try {
                assign.assign(identityAuth, curIdentityAuthVo);
                curIdentityAuthVo.setUsername(user.getUsername());
                identityAuthVos.add(curIdentityAuthVo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        },LinkedList::addAll);
        assign.assign(identityAuthPage, identityAuthVoPage);
        identityAuthVoPage.setRecords(identityAuthVoList);
        return identityAuthVoPage;
    }

    @Override
    public Page<IdentityAuthVo> search(IdentityAuthVo identityAuthVo) throws Exception {
        IdentityAuth identityAuth=new IdentityAuth();
        Page<IdentityAuth> page=new Page<>();
        assign.assign(identityAuthVo,identityAuth,"type,status,ctime,mtime,atime,community");
        assign.assign(identityAuthVo,page,"$current,$size");
        return getIdentityAuthVoPage(identityAuthDao.selectPage(page, BeanUtils.bean2QueryWrapper(IdentityAuth.class,identityAuth)));
    }

    @Override
    public boolean userApplyIdentityAuth(IdentityAuthVo identityAuthVo) throws Exception {
        IdentityAuth identityAuth=new IdentityAuth();
        assign.assign(identityAuthVo,identityAuth,"$type,$community");
        //申请社区长
        if (identityAuth.getType()==1){
            synchronized (this){
                //无社区长
                if (Objects.isNull(identityAuthDao.selectOne(BeanUtils.bean2QueryWrapper(IdentityAuth.class,identityAuth)))){
                    identityAuth.setUid(UserUtils.getCurrentUser().getId());
                    identityAuthDao.insert(identityAuth);
                    return true;
                }else {
                    throw new BizException("该社区已存在社区长");
                }
            }
        }else if (identityAuth.getType()==0){
            //申请居民
            identityAuth.setUid(UserUtils.getCurrentUser().getId());
            identityAuthDao.insert(identityAuth);
        }
        return false;
    }

}
